package com.example.demogateway;

import com.alibaba.fastjson.JSON;
import com.example.common.constants.AuthContants;
import com.example.demogateway.filters.NeedLoginGateWayFilterFactory;
import com.example.demogateway.filters.NoNeedLoginGateWayFilterFactory;
import com.example.demogateway.utils.RestResponse;
import com.netflix.hystrix.strategy.HystrixPlugins;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.gateway.filter.factory.HystrixGatewayFilterFactory;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.http.server.RequestPath;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.reactive.DispatcherHandler;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

/**
 * 参考网址：
 * 	https://www.springcloud.cc/spring-cloud-greenwich.html#_addrequestheader_gatewayfilter_factory
 */
@RestController
@SpringBootApplication
public class DemogatewayApplication {
	private static final Logger logger = LoggerFactory.getLogger(DemogatewayApplication.class);


	@PostConstruct
	public void init() {

	}


	@RequestMapping("/hystrixfallback")
	@ResponseBody
	public RestResponse hystrixfallback(	ServerHttpRequest request) {
		List<String> list = request.getHeaders().getAccessControlRequestHeaders();
		logger.info("请求链路为={}", JSON.toJSON(list));
		String  traceId = MDC.get("traceId");
		logger.info("服务超时={}",traceId);
		RestResponse<String> wsResponse = RestResponse.build(AuthContants.TIMEOUT_FAILURE_CODE,"服务超时");
		return wsResponse;
	}


	/**
	 * needLoginGateWayFilterFactory和noNeedLoginGateWayFilterFactory的区别是
	 *  needLoginGateWayFilterFactory增加了验证，如果没有登录则返回提示信息，
	 *  noNeedLoginGateWayFilterFactory只是将token和登录用户身份进行透传
	 */
	@Autowired
	private NeedLoginGateWayFilterFactory needLoginGateWayFilterFactory;
	@Autowired
	private NoNeedLoginGateWayFilterFactory noNeedLoginGateWayFilterFactory;


//	熔断器
//	@Bean
//	public HystrixGatewayFilterFactory hystrixGatewayFilterFactory(DispatcherHandler dispatcherHandler) {
//		return new HystrixGatewayFilterFactory(dispatcherHandler);
//	}


	@Bean
	public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {

		NeedLoginGateWayFilterFactory.Config conifg = new NeedLoginGateWayFilterFactory.Config();

		NoNeedLoginGateWayFilterFactory.Config noNeedConifg = new NoNeedLoginGateWayFilterFactory.Config();


		Consumer<HystrixGatewayFilterFactory.Config> configConsumer = new Consumer<HystrixGatewayFilterFactory.Config>() {
			@Override
			public void accept(HystrixGatewayFilterFactory.Config config) {
				config.setFallbackUri("forward:/hystrixfallback");
				config.setName("test3000");
			}
		};

		RouteLocator locator =  builder.routes()
				.route("predicate_route", r -> r.order(1)
						.predicate(exchange ->{
							//自定义匹配器，如果匹配"/httpbin"开头,则跳转到对应的网站
							ServerHttpRequest request = exchange.getRequest();
							RequestPath requestPath =  request.getPath();
							String requestPathString = requestPath.value().toString();

							boolean isMatch = requestPathString.startsWith("/httpbin");
							return isMatch;

						})
						.filters(f->
								  {
//								  	多个filter一起使用
//									  return f.removeRequestHeader("Origin")
//											  .rewritePath("/httpbin","")
//											  .hystrix(configConsumer)
//											  ;
									   return f.filter(needLoginGateWayFilterFactory.apply(conifg)).rewritePath("/httpbin","").hystrix(configConsumer);


								}
						)
						.uri("http://localhost:81"))
//				支持路径测试
				.route("path_route", r -> r.order(2).path("/get")

						.uri("http://httpbin.org:80"))

				.route("host_form_route",
						r -> r.order(3).host("**.myhost.org").and().path("/uploadimg3")
						.filters(f -> f.filter(needLoginGateWayFilterFactory.apply(conifg)))
						.uri("http://localhost:81/uploadImg2"))

				.route("path_route_complex", r -> r.order(4).path("/uploadimg4")
						.filters(f -> f.filter(needLoginGateWayFilterFactory.apply(conifg)))
						.uri("http://localhost:81"))
				.route("hystrix_fallback_route", r -> r.order(5).host("*.hystrixfallback.org")
						.filters(f -> f.hystrix(c -> c.setName("slowcmd").setFallbackUri("forward:/hystrixfallback")))
								.uri("http://httpbin.org"))
				.route("path_route2", r -> r.order(6).path("/needLogin")
						.filters(f->
						{
							//需要登录才能使用
							return f.filter(needLoginGateWayFilterFactory.apply(conifg)).hystrix(configConsumer);
						})
						//验证下游需要登录的的应用是否可以获取登录用户身份
						.uri("http://localhost:81"))
				.route("path_route3", r -> r.order(7).path("/hello")
						.filters(f->
						{
							//需要登录才能使用，并透传traceid
							return f.filter(needLoginGateWayFilterFactory.apply(conifg)).hystrix(configConsumer);

						})
						//验证下游需要登录的的应用是否可以获取登录用户身份
						.uri("http://localhost:81"))
				.route("path_route4", r -> r.order(7).path("/noneedlogin")
						.filters(f->
						{
							//如果有用户身份的话将用户身份进行透传，并透传traceid
							return f.filter(noNeedLoginGateWayFilterFactory.apply(noNeedConifg)).hystrix(configConsumer);

						})
						//验证下游需要登录的的应用是否可以获取登录用户身份
						.uri("http://localhost:81"))
				.route("path_route5", r -> r.order(7).path("/timeout")
						.filters(f->
						{
							//需要登录才能使用
							return f.filter(needLoginGateWayFilterFactory.apply(conifg)).hystrix(configConsumer);

						})
						//验证下游需要登录的的应用是否可以获取登录用户身份
						.uri("http://localhost:81"))
				.route("path_route6", r -> r.order(8).path("/resouce/list")
						.filters(f->
						{
							//需要登录才能使用
							return f.filter(needLoginGateWayFilterFactory.apply(conifg)).hystrix(configConsumer);

						})
						//验证下游需要登录的的应用是否可以获取登录用户身份
						.uri("http://localhost:81"))
				.route("path_route7", r -> r.order(9).path("/resouce/info")
						.filters(f->
						{
							//需要登录才能使用
							return f.filter(needLoginGateWayFilterFactory.apply(conifg)).hystrix(configConsumer);

						})
						//验证下游需要登录的的应用是否可以获取登录用户身份
						.uri("http://localhost:81"))
				.route("path_route8", r -> r.order(10).path("/uploadimg4").or().path("/uploadImg2")
//
						.filters(f->
						{
							//需要登录才能使用
							return f.filter(needLoginGateWayFilterFactory.apply(conifg)).hystrix(configConsumer);

						})
						//验证下游需要登录的的应用是否可以获取登录用户身份
						.uri("http://localhost:81"))
				.route("path_route9", r -> r.order(11).path("/app404")
//
						.filters(f->
						{
							//需要登录才能使用
							return f.filter(noNeedLoginGateWayFilterFactory.apply(noNeedConifg)).hystrix(configConsumer);

						})
						//验证下游需要登录的的应用是否可以获取登录用户身份
						.uri("http://localhost:81"))






				.build();
		return locator;
	}
	public static void main(String[] args) {
		SpringApplication.run(DemogatewayApplication.class, args);
	}

}
